package com.dj.ms.interceptor;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import com.dj.ms.annotation.Interceptor;
import com.dj.ms.annotation.Unauthorize;
import com.dj.ms.session.SessionCollector;
import com.dj.ms.session.PrincipalHandler;
import com.dj.ms.session.Principal;
import com.dj.ms.support.SpringBeanFactoryUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.Ordered;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <br>
 * <p>Http servlet签名拦截器</p>
 *
 * <br>
 *
 * @author ZJG
 * @version 1.0
 * @date 2021/8/4 上午9:36
 */
@Slf4j
@Interceptor(order = Ordered.LOWEST_PRECEDENCE - 99)
@ConditionalOnClass(SessionCollector.class)
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private SessionCollector sessionCollector;

    private String activeProfiles;

    public AuthenticationInterceptor(String activeProfiles) {
        this.activeProfiles = activeProfiles;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (ObjectUtil.isNull(this.sessionCollector)) {
            this.sessionCollector = SpringBeanFactoryUtils.getBean("sessionCollector");
        }
        boolean isUnAuth = (handler instanceof HandlerMethod)
                && (null != ((HandlerMethod)handler).getMethodAnnotation(Unauthorize.class));

        Principal principal = PrincipalHandler.buildSessionSerializable(request, activeProfiles, isUnAuth);
        if (ObjectUtils.isNotEmpty(principal)) {
            if (ObjectUtil.isNotNull(this.sessionCollector)) {
                String pairKey = PrincipalHandler.buildPairKey(principal);
                this.sessionCollector.collect(new Pair<>(pairKey, principal));
            }
            return true;
        }
        log.error("Authentication fail. return false.");
        return false;
    }

}
